package online.inote.mapper.core;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import lombok.Getter;
import online.inote.mapper.annotation.GenerateMapper;
import online.inote.mapper.utils.ClassUtils;

public abstract class Generator extends ClassLoader {
	
	protected Logger logger = LoggerFactory.getLogger(getClass());

	@Getter
	public enum Type {
		MAPPER("Mapper"), SERVICE("Service");

		private String name;

		Type(String name) {
			this.name = name;
		}
	}

	public abstract Type getType();
	
	public String getClassName(Class<?> generic) {
		GenerateMapper anno = generic.getAnnotation(GenerateMapper.class);
		
		if (anno == null) {
			throw new RuntimeException("获取注解信息失败");
		}
		
		return getPackage(generic, anno) + "." + getName(generic, anno);
	}
	
	public String getName(Class<?> generic, GenerateMapper anno) {
		
		String simpleName = generic.getSimpleName();

		if (Type.MAPPER.equals(getType())) {
			if (StringUtils.isNotBlank(anno.mapperName())) {
				return anno.mapperName();
			}
		} else {
			if (StringUtils.isNotBlank(anno.serviceName())) {
				return anno.mapperName();
			}
		}
		
		return simpleName.replace(anno.signatureSuffix(), getType().getName());
	}
	
	public String getPackage(Class<?> generic, GenerateMapper anno) {
		
		if (Type.MAPPER.equals(getType())) {
			if (StringUtils.isNotBlank(anno.generateMapperPath())) {
				return anno.generateMapperPath();
			}
		} else {
			if (StringUtils.isNotBlank(anno.generateServicePath())) {
				return anno.generateServicePath();
			}
		}
		
		String name = generic.getName();
		
		if (name.length() - name.replace(".", "").length() > 2) {
			return name.substring(0, name.lastIndexOf(".", name.lastIndexOf(".") - 2)) + "."
					+ getType().getName().toLowerCase();
		} else {
			return getType().getName().toLowerCase();
		}
	}
	
	public String getPath(String className) {
		return StringUtils.replace(className, ".", "/");
	}
	
	public String getSignature(Class<?> generic, Class<?> superClass) {
		
		StringBuffer buffer = new StringBuffer();

		if (Type.MAPPER.equals(getType())) {
			buffer.append("Ljava/lang/Object;");
		}

		buffer.append("L").append(ClassUtils.getClassPath(superClass));
		buffer.append("<L").append(ClassUtils.getClassPath(generic)).append(";>;");
		
		return buffer.toString();
	}
}